package com.lxxin.service.impl;

import com.lxxin.dao.TypeDao;
import com.lxxin.pojo.Type;
import com.lxxin.service.TypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class TypeServiceImpl implements TypeService {
    @Autowired
    private TypeDao typeDao;

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    public Long saveType(Type type) {
        Type typeByName = findTypeByName(type.getName());
        if (typeByName != null) {
            return 0L;
        }
        return typeDao.saveType(type);
    }

    @Override
    public Type findTypeById(Long id) {
        return typeDao.findTypeById(id);
    }

    @Override
    public Type findTypeByName(String name) {
        return typeDao.findTypeByName(name);
    }

    @Override
    public List<Type> findTypeList() {
        List<Type> typeList = typeDao.findTypeList();
        typeList.forEach(x -> x.getBlogCount());
        List<Type> newTypeList = setTypeList(typeList);
        newTypeList = newTypeList.stream().sorted(Comparator.comparingInt(Type::getBlogCount))
                .collect(Collectors.toList());
        return newTypeList;
    }

    @Override
    public List<Type> findTopTypeList(Integer top) {
        List<Type> typeList = typeDao.findTypeList();
        Collections.sort(typeList, (a, b) -> b.getBlogCount() - a.getBlogCount());
        if (top > typeList.size()) {
            top = typeList.size();
        }
        List<Type> types = new ArrayList<>(typeList.subList(0, top));
        return types;
    }

    @Override
    public int updateType(Type type) {
        return typeDao.updateType(type);
    }

    @Override
    public void deleteType(Long id) {
        typeDao.deleteType(id);
    }

    public List<Type> setTypeList(List<Type> typeList) {
        List<Type> newTypeList = new ArrayList<>();
        for (Type type : typeList) {
            if (type.getParentId() == null) {
                newTypeList.add(type);
                List<Type> childList = getChildType(type, typeList);
                type.setChildTypes(childList);
            }
        }
        return newTypeList;
    }

    public List<Type> getChildType(Type type, List<Type> typeList) {
        ArrayDeque<Type> queue = new ArrayDeque<>();
        List<Type> childList = new ArrayList<>();
        queue.addLast(type);
        while (!queue.isEmpty()) {
            Type tmpParent = queue.removeFirst();
            for (Type t : typeList) {
                if (t.getParentId() != null && t.getParentId().equals(tmpParent.getId())) {
                    childList.add(t);
                    queue.addLast(t);
                }
            }
        }
        return childList;
    }
}
